﻿using System;
using System.Diagnostics.Contracts;
using ZenMoney.Core.DataAccess.Mappings;

namespace ZenMoney.Core.Entities
{
    public abstract class BaseEntity
    {
        public virtual int? Id { get; protected set; }

        public virtual int Version { get; set; }

        [Ignore]
        public virtual int DbId
        {
            get
            {
                Contract.Requires<InvalidOperationException>(
					IsTransient, Messages.EntityIsTransientError);
                return Id.Value;
            }
        }

        [Ignore]
        public virtual bool IsTransient
        {
            get
            {
                return Id.HasValue;
            }
        }

        [Ignore]
        public virtual Type UnproxiedType
        {
            get { return GetType(); }
        }

        public virtual bool Equals(BaseEntity other)
        {
            if (other == null)
                return false;

            if (ReferenceEquals(this, other))
                return true;

            if (!IsTransient && 
                !other.IsTransient && 
                Equals(Id, other.Id))
            {
                var otherType = other.UnproxiedType;
                var thisType = UnproxiedType;
                return thisType.IsAssignableFrom(otherType) ||
                otherType.IsAssignableFrom(thisType);
            }

            return false;
        }

        public override bool Equals(object obj)
        {
            return Equals(obj as BaseEntity);
        }

        public override int GetHashCode()
        {
            return IsTransient ? 
				Id.GetHashCode() : 
				base.GetHashCode();
        }
    }
}
